package org.jtrace.swing;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.ButtonModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;

import org.jtrace.Material;
import org.jtrace.Materials;
import org.jtrace.Scene;
import org.jtrace.SphericalTexture;
import org.jtrace.Tracer;
import org.jtrace.ViewPlane;
import org.jtrace.examples.swing.App;
import org.jtrace.geometry.BoundedMesh;
import org.jtrace.geometry.Mesh;
import org.jtrace.geometry.OctreeMesh;
import org.jtrace.primitives.ColorRGB;
import org.jtrace.primitives.ReflectanceCoefficient;

public class TracerPanel extends JPanel {

  private static final long serialVersionUID = 6707782783340362498L;

  private Tracer tracer;
  private Scene scene;
  private ViewPlane viewPlane;
  
  private JProgressBar progressBar;
  
  private int height;
  private int width;
  private DrawablePanel drawablePanel;
  
  private String malhaPath = null;
  private String texturePath = null;
  JFileChooser fc = new JFileChooser();
  
  public TracerPanel(Tracer tracer, Scene scene, ViewPlane viewPlane) {
    this(tracer, scene, viewPlane, 300, 300);
  }
  
  public TracerPanel(Tracer tracer, Scene scene, ViewPlane viewPlane, int width, int height) {
    super();
    
    this.tracer = tracer;
    this.scene = scene;
    this.viewPlane = viewPlane;
    this.width = width;
    this.height = height;
    
    this.progressBar = new JProgressBar(0, width * height);
    
    setLayout(new BorderLayout());
    prepareAspectRatio();
    init();
  }

  private void prepareAspectRatio() {
    float aspect = (float) viewPlane.getHres() / (float) viewPlane.getVres(); 
    int newheight = Math.round(height / aspect);
    
    setPreferredSize(new Dimension(width, newheight));
  }

  private void init() {
    drawablePanel = new DrawablePanel();
    
    SwingListener listener = new SwingListener(this);
    tracer.addListeners(listener);

    final JCheckBox malhaCB = new JCheckBox("malha");
    malhaCB.addActionListener(new ActionListener() {

		@Override
		public void actionPerformed(ActionEvent arg0) {
			AbstractButton abstractButton = (AbstractButton) arg0.getSource();
			ButtonModel buttonModel = abstractButton.getModel();
			if (buttonModel.isSelected()) {
				if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
					malhaPath = fc.getSelectedFile().getName();
				} else {
					buttonModel.setSelected(false);
				}
			}
		}
	});
    
    final JCheckBox textureCB = new JCheckBox("textura");
    textureCB.addActionListener(new ActionListener() {

		@Override
		public void actionPerformed(ActionEvent arg0) {
			AbstractButton abstractButton = (AbstractButton) arg0.getSource();
			ButtonModel buttonModel = abstractButton.getModel();
			if (buttonModel.isSelected()) {
				if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
					texturePath = fc.getSelectedFile().getAbsolutePath();
				} else {
					buttonModel.setSelected(false);
				}
			}
		}
	});
    
    JPanel checkBoxOptionPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
    checkBoxOptionPanel.add(malhaCB);
    checkBoxOptionPanel.add(textureCB);
    
    final ArrayList<JRadioButton> renderOptions = new ArrayList<JRadioButton>();
    
    renderOptions.add(new JRadioButton("sem bounding box"));
    renderOptions.add(new JRadioButton("com bounding box"));
    renderOptions.add(new JRadioButton("com octree"));
    renderOptions.get(1).setSelected(true);
    
    ButtonGroup renderButtonGroup = new ButtonGroup();
    JPanel renderOptionPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
    for (JRadioButton option : renderOptions) {
    	renderButtonGroup.add(option);
    	renderOptionPanel.add(option);
    }

    final ReflectanceCoefficient kAmbient = new ReflectanceCoefficient(0.07, 0.07, 0.07);
    final ReflectanceCoefficient kDiffuse = new ReflectanceCoefficient(0.3, 0.3, 0.3);
    final ReflectanceCoefficient kSpecular = new ReflectanceCoefficient(0.1, 0.1, 0.1);
    
    JButton renderBtn = new JButton("Render");
    renderBtn.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        progressBar.setString(null);
        
        // Selecao de malha
        String plyPath = "beethoven.ply";
        if (malhaCB.isSelected()) {
        	plyPath = malhaPath;
        }
        
        // Selecao de textura
        Material material = null;
        if (textureCB.isSelected()) {
            //texturePath = "C:\\Users\\faithos\\Desktop\\eclipse\\workspace\\JTrace\\src\\examples\\org\\jtrace\\examples\\swing\\bricks.bmp";
        	material = new SphericalTexture(texturePath, ColorRGB.RED, kAmbient, kDiffuse, kSpecular);
        } else {
        	material = Materials.metallic(ColorRGB.RED);
        }
        
        // Render option
        Mesh mesh = null;
        if (renderOptions.get(0).isSelected()) {
        	mesh = new Mesh(plyPath, material);
        } else if (renderOptions.get(1).isSelected()) {
        	mesh = new BoundedMesh(plyPath, material);
        } else {
        	mesh = new OctreeMesh(plyPath, material);
        }
        
        scene.getObjects().clear();
        scene.add(App.createPlane());
        scene.add(mesh);
        
        new Thread() {
          @Override
          public void run() {
            tracer.render(scene, viewPlane);
          }
        }.start();
      }
    });
    
    JPanel renderPanel = new JPanel(new GridLayout(3, 1));
    renderPanel.add(checkBoxOptionPanel);
    renderPanel.add(renderOptionPanel);
    renderPanel.add(renderBtn);
    
    JPanel statusPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 5));
    
    progressBar.setValue(0);
    progressBar.setStringPainted(true);
    
    statusPanel.add(progressBar);
    
    JScrollPane scrollPane = new JScrollPane(drawablePanel);
    
    add(statusPanel, BorderLayout.PAGE_END);
    add(scrollPane, BorderLayout.CENTER);
    //add(drawablePanel, BorderLayout.CENTER);
    add(renderPanel, BorderLayout.PAGE_START);
  }
  
  public DrawablePanel getDrawablePanel() {
    return drawablePanel;
  }
  
  public void pixelsPainted(int pixels) {
    progressBar.setValue(pixels);
  }
  
  public void resetProgressBar() {
    progressBar.setString("Inactive");
  }
}